package com.rrd.itext.utils.pdf2Image;

import org.jpedal.PdfDecoder;
import org.jpedal.color.ColorSpaces;
import org.jpedal.constants.PageInfo;
import org.jpedal.exception.PdfException;
import org.jpedal.fonts.FontMappings;
import com.rrd.itext.utils.IOUtil;

import java.awt.*;
import java.awt.image.BufferedImage;
import java.io.ByteArrayOutputStream;
import java.io.File;
import java.io.FileNotFoundException;
import java.io.IOException;
import java.util.Iterator;

public class PDF2Image {
    /**use 96 dpi as default so pages correct size (72 will be smaller)*/
    private int dpi=96;
    
    private String fileName;
    
    private boolean isURL;

    /**the decoder object which decodes the pdf and returns a data object*/
    PdfDecoder decode_pdf = null;

    //type of image to save thumbnails
    private String format = "png";
    
    private java.util.List<byte[]> imageList;
    
    /**scaling to use - default is 100 percent*/
    private int scaling=100;

    public static PDF2Image getInstance(String fileName){
        return new PDF2Image(fileName);
    }
    public static PDF2Image getInstance(String fileName, boolean isURL){
        return new PDF2Image(fileName, isURL);
    }
    
    private PDF2Image(String fileName) {
        format="jpg";
        this.fileName = fileName;
        this.isURL = false;
        imageList = new java.util.ArrayList<byte[]>();
    }    
    private PDF2Image(String fileName, boolean isURL) {
        format="jpg";
        this.isURL = isURL;
        this.fileName = fileName;
        imageList = new java.util.ArrayList<byte[]>();
    }
    /**
     * Get images byte[] list
     */
    public java.util.List<byte[]> toImages() {
        try {
            decode_pdf = new PdfDecoder(true);
            FontMappings.setFontReplacements();
            decode_pdf.setExtractionMode(0, dpi,dpi/72f);
            if(this.isURL){
                decode_pdf.openPdfFileFromURL(this.fileName, true);
            }else{
                decode_pdf.openPdfFile(fileName);
            }
        } catch (Exception e) {
            System.err.println("Exception " + e + " in pdf code in "+fileName);          
        }

        int start = 1,  end = decode_pdf.getPageCount();

        try {
            BufferedImage[] multiPages = new BufferedImage[1 + (end-start)];
            for (int page = start; page < end + 1; page++){
                getPage(start, end,multiPages, page);
            }
        } catch (Exception e) {
            decode_pdf.closePdfFile();
            throw new RuntimeException("Exception " + e.getMessage()+" with thumbnails on File="+this.fileName);
        }
        decode_pdf.closePdfFile();
        return imageList;
    }

    /**
     * Get the first image byte[]
     */
    public byte[] toSingleImage(){
        return toImages().get(0);
    }
    
    /**
     * Persist the images to imageDir
     */
    public void toImages(String imageDir){
        java.util.List<byte[]> list =  toImages();
        int i = 0;
        for(byte[] imageBytes : list){
            i++;
            IOUtil.bytes2File(imageBytes, imageDir + i +".jpg");
        }
    }

    private void getPage(int start, int end, BufferedImage[] multiPages, int page) throws PdfException,
            IOException, FileNotFoundException {
            System.out.println("generating " + page + " page");
            String pageAsString=String.valueOf(page);
            String maxPageSize=String.valueOf(end);
            int padding=maxPageSize.length()-pageAsString.length();
            for(int ii=0;ii<padding;ii++){
                pageAsString='0'+pageAsString;
            }
            BufferedImage image_to_save = decode_pdf.getPageAsImage(page);

            Iterator colorspacesUsed=decode_pdf.getPageInfo(PageInfo.COLORSPACES);

            int nextID;
            boolean isGrayOnly=colorspacesUsed!=null; //assume true and disprove
            while(colorspacesUsed!=null && colorspacesUsed.hasNext()){
                nextID=((Integer)(colorspacesUsed.next())).intValue();
                if(nextID!= ColorSpaces.DeviceGray && nextID!=ColorSpaces.CalGray){
                    isGrayOnly=false;
                }
            }

            if(isGrayOnly){
                BufferedImage image_to_save2=new BufferedImage(image_to_save.getWidth(),image_to_save.getHeight(), BufferedImage.TYPE_BYTE_GRAY);
                image_to_save2.getGraphics().drawImage(image_to_save,0,0,null);
                image_to_save = image_to_save2;
            }
            if (image_to_save != null) {
                String maxDimensionAsString = System.getProperty("maxDimension");
                int maxDimension = -1;

                if(maxDimensionAsString != null){
                    maxDimension = Integer.parseInt(maxDimensionAsString);
                }
                if(scaling!=100 || maxDimension != -1){
                    int newWidth=image_to_save.getWidth()*scaling/100;
                    int newHeight=image_to_save.getHeight()*scaling/100;

                    Image scaledImage=null;
                    if(maxDimension != -1 && (newWidth > maxDimension || newHeight > maxDimension)){
                        if(newWidth > newHeight){
                            newWidth = maxDimension;
                            scaledImage= image_to_save.getScaledInstance(newWidth,-1,BufferedImage.SCALE_SMOOTH);
                        } else {
                            newHeight = maxDimension;
                            scaledImage= image_to_save.getScaledInstance(-1,newHeight,BufferedImage.SCALE_SMOOTH);
                        }
                    } else {
                        scaledImage= image_to_save.getScaledInstance(newWidth,-1,BufferedImage.SCALE_SMOOTH);
                    }

                    if(format.toLowerCase().startsWith("jp")){
                        image_to_save = new BufferedImage(scaledImage.getWidth(null),scaledImage.getHeight(null) , BufferedImage.TYPE_INT_RGB);
                    }else{
                        image_to_save = new BufferedImage(scaledImage.getWidth(null),scaledImage.getHeight(null) , BufferedImage.TYPE_INT_ARGB);
                    }
                    Graphics2D g2 = image_to_save.createGraphics();
                    g2.drawImage(scaledImage, 0, 0,null);
                }
                //save image
                //decode_pdf.getObjectStore().saveStoredImage(output_dir + pageAsString + image_name, image_to_save, true, false, format);
                //java.io.FileOutputStream out = new java.io.FileOutputStream(output_dir + page + image_name+".jpg");
                ByteArrayOutputStream imageOutputStream = new ByteArrayOutputStream();
                javax.imageio.ImageIO.write((java.awt.image.RenderedImage)image_to_save,"jpg", imageOutputStream);
                imageList.add(imageOutputStream.toByteArray());
            }
            decode_pdf.flushObjectValues(true);
    }

    public static void main(String[] args) {
        PDF2Image.getInstance("http://127.0.0.1:8080/iTextService/images/samplePDF-23.pdf", true).toImages("D:\\a\\");
    }
    
}
